package apartado4;

import java.util.LinkedHashSet;
import java.util.Set;

import aima.core.agent.Action;
import aima.core.search.framework.ActionsFunction;
import aima.core.search.framework.ResultFunction;

public class AtascoFunctionFactory {

	private static ActionsFunction _actionsFunction = null;
	private static ResultFunction _resultFunction = null;
	
	public static ActionsFunction getActionsFunction() 
	{
		if (null == _actionsFunction) 
		{
			_actionsFunction = new AtascoActionsFunction();
		}
		return _actionsFunction;
	}
	
	public static ResultFunction getResultFunction() 
	{
		if (null == _resultFunction) 
		{
			_resultFunction = new AtascoResultFunction();
		}
		return _resultFunction;
	}
	
	private static class AtascoResultFunction implements ResultFunction
	{

		public Object result(Object s, Action a) {
			EstadoAtasco nuevoEstado;
			EstadoAtasco estado = (EstadoAtasco) s;
			
			if (EstadoAtasco.A_A.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(0, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_A.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(0, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_V.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(1, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_V.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(1, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_R.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(2, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_R.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(2, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_S.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(3, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_S.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(3, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_C1.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(4, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_C1.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(4, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_C2.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(5, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_C2.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(5, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_G.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(6, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_G.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(6, false);
				return nuevoEstado;
			}else if (EstadoAtasco.A_Z.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(7, true);
				return nuevoEstado;
			}else if (EstadoAtasco.R_Z.equals(a)){
				nuevoEstado = new EstadoAtasco(estado);
				nuevoEstado.mueve(7, false);
				return nuevoEstado;
			}
			
			return s;
		}
		
	}
	
	private static class AtascoActionsFunction implements ActionsFunction
	{

		public Set<Action> actions(Object state) {
			EstadoAtasco estado = (EstadoAtasco) state;
			Set<Action> actions = new LinkedHashSet<Action>();
			if (estado.movimientoValido(EstadoAtasco.A_A))
				actions.add(EstadoAtasco.A_A);
			if (estado.movimientoValido(EstadoAtasco.R_A))
				actions.add(EstadoAtasco.R_A);
			
			if (estado.movimientoValido(EstadoAtasco.A_V))
				actions.add(EstadoAtasco.A_V);
			if (estado.movimientoValido(EstadoAtasco.R_V))
				actions.add(EstadoAtasco.R_V);
			
			if (estado.movimientoValido(EstadoAtasco.A_R))
				actions.add(EstadoAtasco.A_R);
			if (estado.movimientoValido(EstadoAtasco.R_R))
				actions.add(EstadoAtasco.R_R);
			
			if (estado.movimientoValido(EstadoAtasco.A_S))
				actions.add(EstadoAtasco.A_S);
			if (estado.movimientoValido(EstadoAtasco.R_S))
				actions.add(EstadoAtasco.R_S);
			
			if (estado.movimientoValido(EstadoAtasco.A_C1))
				actions.add(EstadoAtasco.A_C1);
			if (estado.movimientoValido(EstadoAtasco.R_C1))
				actions.add(EstadoAtasco.R_C1);
			
			if (estado.movimientoValido(EstadoAtasco.A_C2))
				actions.add(EstadoAtasco.A_C2);
			if (estado.movimientoValido(EstadoAtasco.R_C2))
				actions.add(EstadoAtasco.R_C2);
			
			if (estado.movimientoValido(EstadoAtasco.A_G))
				actions.add(EstadoAtasco.A_G);
			if (estado.movimientoValido(EstadoAtasco.R_G))
				actions.add(EstadoAtasco.R_G);
			
			if (estado.movimientoValido(EstadoAtasco.A_Z))
				actions.add(EstadoAtasco.A_Z);
			if (estado.movimientoValido(EstadoAtasco.R_Z))
				actions.add(EstadoAtasco.R_Z);
			
			return actions;
		}
		
	}
}
